package cn.matrix42.potoo.format.json.parser;

import cn.matrix42.potoo.annotation.Public;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

@Public
public class JsonObject extends JsonNode {

    private final Map<String, JsonNode> map = new LinkedHashMap<>();

    public JsonObject() {
    }

    @Override
    public boolean isJsonObject() {
        return true;
    }

    @Override
    public boolean isJsonArray() {
        return false;
    }

    @Override
    public boolean isJsonLiteral() {
        return false;
    }

    @Override
    public boolean isNull() {
        return false;
    }

    @Override
    protected String toNormalJson() {
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        Set<Entry<String, JsonNode>> entrySet = map.entrySet();
        int i = 0;
        for (Entry<String, JsonNode> entry : entrySet) {
            sb.append("\"").append(entry.getKey()).append("\"").append(":");
            sb.append(entry.getValue().toNormalJson());
            if (i < entrySet.size() - 1) {
                sb.append(",");
            }
            i++;
        }
        sb.append("}");
        return sb.toString();
    }

    @Override
    protected String toPrettyJson(int level) {
        StringBuilder sb = new StringBuilder();
        sb.append("{\n");
        Set<Entry<String, JsonNode>> entrySet = map.entrySet();
        int i = 0;
        for (Entry<String, JsonNode> entry : entrySet) {
            sb.append(align(level));
            sb.append("\"").append(entry.getKey()).append("\"").append(":");
            sb.append(entry.getValue().toPrettyJson(level + 1));
            if (i < entrySet.size() - 1) {
                sb.append(",\n");
            }
            i++;
        }
        if (!entrySet.isEmpty()) {
            sb.append("\n");
            sb.append(align(level - 1));
        }
        sb.append("}");
        return sb.toString();
    }

    @Override
    public ObjectType getObjectType() {
        return ObjectType.JSON_OBJECT;
    }

    public int size() {
        return map.size();
    }

    public boolean isEmpty() {
        return map.isEmpty();
    }

    public boolean containsKey(String key) {
        return map.containsKey(key);
    }

    public boolean containsValue(JsonNode value) {
        return map.containsValue(value);
    }

    public JsonNode get(String key) {
        return map.get(key);
    }

    public JsonObject put(String key, JsonLiteral jsonLiteral) {
        putInternal(key, jsonLiteral);
        return this;
    }

    public JsonObject put(String key, JsonArray jsonArray) {
        putInternal(key, jsonArray);
        return this;
    }

    public JsonObject put(String key, JsonObject jsonObject) {
        putInternal(key, jsonObject);
        return this;
    }

    public JsonNode remove(String key) {
        return map.remove(key);
    }

    public void putAll(Map<? extends String, ? extends JsonNode> m) {
        map.putAll(m);
    }

    public void clear() {
        map.clear();
    }

    public Set<String> keySet() {
        return map.keySet();
    }

    public Collection<JsonNode> values() {
        return map.values();
    }

    public Set<Entry<String, JsonNode>> entrySet() {
        return map.entrySet();
    }

    private void putInternal(String key, JsonNode jsonNode) {
        map.put(key, jsonNode);
    }

}
